/*
 * fat32.h
 *
 *  Created on: 20/09/2011
 *      Author: alejandro
 */

#ifndef FAT32_H_
#define FAT32_H_


#include "direccionamiento.h"
#include <string.h>
#include <stdint.h>
#include <math.h>
#include <stdlib.h>
#include "queue.h"

typedef enum{
	noModificado=0,
	modificado=1
}bitDeUso;

typedef struct {
	uint8_t jmpBoot[3];
	uint8_t oemName[8];
	uint16_t bytesPerSec;  //fijo
	uint8_t secPerClus;    //importante
	uint16_t rsvdSecCnt;   //
	uint8_t numFats;       //
	uint16_t rootEntCnt;
	uint16_t totSec16;
	uint8_t media;
	uint16_t fatz16;
	uint16_t secPerTrk;
	uint16_t numHeads;
	uint32_t hiddSec;
	uint32_t totSec32;
	uint32_t secPerFat; //sectores por tabla fat
	uint16_t extFlags;
	uint16_t fsVer;
	uint32_t rootClus;  //
	uint16_t fsInfo;
	uint16_t bkBootSec;
	uint8_t reserved[12];
	uint8_t drvNum;
	uint8_t reserved1;
	uint8_t bootSig;
	uint32_t volID;
	uint8_t volLab[11];
	uint8_t filSysType[8];
	uint8_t bootCode[420];
	uint16_t bootSecSig;
}__attribute__((packed)) Boot_Sector;


typedef struct {
	uint8_t Name[8];            //name[0] no puede ser e5 o 00
	uint8_t ext[3];				//
	uint8_t Attr;				//0x10 o 0x20
	uint8_t NTRes;				//
	uint8_t CrtTimeTenth;		//no lo usamos
	uint16_t CrtTime;			//no lo usamos
	uint16_t CrtDate;			//no lo usamos
	uint16_t LstAccDate;		//no lo usamos
	uint16_t FstClusHI;			//parte alta del numero de cluster
	uint16_t WrtTime;			//no lo usamos
	uint16_t WrtDate;			//no lo usamos
	uint16_t FstClusLO;			//parte baja del numero de cluster
	uint32_t FileSize;			//

}__attribute__((packed)) Dir;

typedef struct {
	uint8_t Ord;				//
	uint8_t Name1[10];
	uint8_t Attr;				//0x0F
	uint8_t Type;				//0x00
	uint8_t Chksum;				//no hay que tocarlo
	uint8_t Name2[12];
	uint16_t FstClusLO;			//0x0000
	uint8_t Name3[4];
}__attribute__((packed)) LDir;

typedef enum{
	verdadero = 1,
	falso = 0,
}archSinClusters;

typedef enum{
	encontrado = 1,
	noEncontrado = 0
}resultadoBusqueda;

typedef struct {
	uint32_t clusterContenido;
	uint32_t posicionDirectorio;
	uint32_t clusterDirectorio;
	int resultadoBusqueda;
}__attribute__((packed)) infoDir;

typedef struct {
	uint32_t offset;
	uint32_t maxIndice;
	uint32_t* tabla;
	int bitDeUso;
}Fat;


extern Boot_Sector BootSector;
extern Fat FAT;

Boot_Sector fat32_LeerBootSector ();
void fat32_LeerFatRegion(uint32_t posicion);
void fat32_EscribirFatRegion();
int fat32_SeEncuentraEnTabla(uint32_t posicion);
uint32_t fat32_SiguienteCadenaFat(uint32_t posicion);
int fat32_esFinDeCadena(uint32_t posicion);

uint32_t fat32_obtenerNumeroDeBloque(uint32_t numeroDeCluster);
uint32_t fat32_ObtenerClustersLibres();
t_queue* fat32_ObtenerNClustersLibres(int n);
void fat32_AgregarACadenaDeClusters(int cantClusters,int posicionFAT);
void fat32_agregarPrimerCluster(Dir *Cluster, infoDir *info);
void fat32_removerPrimerCluster(Dir *Cluster, infoDir *info);
uint32_t fat32_cantidadDeClusterAgregar(uint32_t nuevoFilesize, uint32_t viejoFilesize);
void fat32_RemoverClusterDeCadena(int cantClusters, int posicionFAT, uint32_t* tablaFAT);
void fat32_RemoverClusters(int posicionFAT);
char* fat32_ObtenerCluster(int numeroDeCluster);
void fat32_mandarAEscribirCluster(char *Cluster, uint32_t numeroDeCluster);

//--------------------------------------------------------------
int entradaLibre(char fstLetra);
Dir* fat32_buscarPosLibreEnDirectorio(uint32_t *posLibre, infoDir info);
void fat32_eliminarEntrada(infoDir info);
int fat32_directorioEstaVacio(uint32_t numClus);
char* obtenerNombreUTF8(LDir LFN);
void grabarNombreUTF16(LDir *LFN,char *nombre);
char* obtenerNombreCorto(Dir DIR);
char* nombrePath(const char* path, int* cantLetras);


infoDir buscar(const char* path);
infoDir buscarEnDirectorio(uint32_t numeroCluster,char* nombre);
LDir compararEntrada(Dir Cluster, LDir LFN,  char* nombre,int* encontro,int* flag);

void listarDirectorio(uint32_t numeroCluster, t_queue* colaNombres);
LDir listarEntradaDirectorio(Dir Cluster, LDir LFN, t_queue* colaNombres,int* flag);

#endif /* FAT32_H_ */
